code block
pacman::p_load(ggiraph, plotly, gganimate,
gifski, gapminder,
DT, tidyverse, patchwork, readxl,
urbnthemes, ggthemr, wesanderson)April 28, 2023
Interactive Arguments of ggiraph
Original ggplot dotplot:
set_urbn_defaults(style = "print")
ggplot(data = exam_data,
aes(x = MATHS)) +
geom_dotplot(stackdir = "up",
binwidth = 1,
dotsize = 1) +
scale_y_continuous(NULL, breaks = NULL) +
labs(x = "Math Scores") +
theme(axis.title.y = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank())
With ggiraph tooltips:
Customise information to be included in tooltips by creating a new list
exam_data$tooltip <- c(paste0(
"Name:", exam_data$ID,
"\n Class:", exam_data$CLASS
))
p <- ggplot(data = exam_data,
aes(x = MATHS)) +
geom_dotplot_interactive(
aes(tooltip = exam_data$tooltip),
stackgroups = TRUE,
binwidth = 1,
dotsize = 1,
method = "histodot") +
scale_y_continuous(NULL, breaks = NULL) +
labs(x = "Math Scores")
girafe(
ggobj = p,
width_svg = 6,
height_svg = 6*0.618
)Adding css arguments to opts_tooltip() of ggiraph
tooltip_css <- "background-color:#dfdfeb; font-style:bold; color:black;" #<<
exam_data$tooltip <- c(paste0(
"Name:", exam_data$ID,
"\n Class:", exam_data$CLASS
))
p <- ggplot(data = exam_data,
aes(x = MATHS)) +
geom_dotplot_interactive(
aes(tooltip = exam_data$tooltip),
stackgroups = TRUE,
binwidth = 1,
dotsize = 1,
method = "histodot") +
scale_y_continuous(NULL, breaks = NULL) +
labs(x = "Math Scores")
girafe(
ggobj = p,
width_svg = 6,
height_svg = 6*0.618,
options = list( #<<
opts_tooltip( #<<
css = tooltip_css)) #<<
) Adding stat_summary() calculations in ggplot
ggthemr("flat")
tooltip <- function(y, ymax, accuracy = .01) { #<<
mean <- scales::number(y, accuracy = accuracy) #<<
sem <- scales::number(ymax - y, accuracy = accuracy) #<<
paste("Mean Math Score:", mean, "+/-", sem) #<<
} #<<
p2 <- ggplot(data=exam_data,
aes(x = RACE)) +
stat_summary(aes(y = MATHS,
tooltip = after_stat(tooltip(y, ymax))),
fun.data ="mean_se",
geom = GeomInteractiveCol,
fill = "light blue") +
stat_summary(aes(y = MATHS),
fun.data = mean_se,
geom ="errorbar",
width = 0.2, linewidth = 0.2) +
labs(y ="Math Scores") +
theme(axis.title.x = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
plot.background = element_rect(fill = "#F8F3E6", color = "#F8F3E6"))
girafe(ggobj = p2,
width_svg = 8,
height_svg = 8*0.618)data_id is specified as an aes() argument in the interactive geom functions
e.g: geom_dotplot_interactive(aes(data_id = variablename))
p <- ggplot(data = exam_data,
aes(x = MATHS)) +
geom_dotplot_interactive(
aes(data_id = CLASS), #<<
stackgroups = TRUE,
binwidth = 1,
method = "histodot") +
scale_y_continuous(NULL,
breaks = NULL) +
labs(x ="Math Scores") +
theme(axis.line = element_blank(),
plot.background = element_rect(fill = "#F8F3E6", color = "#F8F3E6"))
girafe(
ggobj = p,
width_svg = 6,
height_svg = 6*0.618
) Customisation Options
p <- ggplot(data = exam_data,
aes(x = MATHS)) +
geom_dotplot_interactive(
aes(data_id = CLASS),
stackgroups = TRUE,
binwidth = 1,
method = "histodot") +
scale_y_continuous(NULL,
breaks = NULL) +
labs(x ="Math Scores") +
theme(axis.line = element_blank(),
plot.background = element_rect(fill = "#F8F3E6", color = "#F8F3E6"))
girafe(
ggobj = p,
width_svg = 6,
height_svg = 6*0.618,
options = list( #<<
opts_hover(css = "fill: #202020;"), #<<
opts_hover_inv(css = "opacity:0.2;") #<<
) #<<
) p <- ggplot(data=exam_data,
aes(x = MATHS)) +
geom_dotplot_interactive(
aes(tooltip = CLASS, #<<
data_id = CLASS),#<<
stackgroups = TRUE,
binwidth = 1,
method = "histodot") +
scale_y_continuous(NULL,
breaks = NULL) +
labs(x ="Math Scores") +
theme(axis.line = element_blank(),
plot.background = element_rect(fill = "#F8F3E6", color = "#F8F3E6"))
girafe(
ggobj = p,
width_svg = 6,
height_svg = 6*0.618,
options = list(
opts_hover(css = "fill: #202020;"),
opts_hover_inv(css = "opacity:0.2;")
)
) When a data point of one of the dotplot is selected, the corresponding data point ID on the second data visualisation will be highlighted too
p1 <- ggplot(data=exam_data,
aes(x = MATHS)) +
geom_dotplot_interactive(
aes(tooltip = CLASS,
data_id = ID),
stackgroups = TRUE,
binwidth = 1,
method = "histodot") +
coord_cartesian(xlim=c(0,100)) + #<<
scale_y_continuous(NULL,
breaks = NULL) +
labs(x ="Math Scores") +
theme(axis.line = element_blank(),
plot.background = element_rect(fill = "#F8F3E6", color = "#F8F3E6"))
p2 <- ggplot(data=exam_data,
aes(x = ENGLISH)) +
geom_dotplot_interactive(
aes(tooltip = CLASS,
data_id = ID),
stackgroups = TRUE,
binwidth = 1,
method = "histodot") +
coord_cartesian(xlim=c(0,100)) + #<<
scale_y_continuous(NULL,
breaks = NULL) +
labs(x ="English Scores") +
theme(axis.line = element_blank(),
plot.background = element_rect(fill = "#F8F3E6", color = "#F8F3E6"))
girafe(code = print(p1 / p2), #<<
width_svg = 6,
height_svg = 6,
options = list(
opts_hover(css = "fill: #202020;"),
opts_hover_inv(css = "opacity:0.2;")
)
) onclick argument opens link up in new window when clicked.
tt <- "click me"
exam_data$onclick <- sprintf("window.open(\"%s%s\")",
"https://www.onemap.gov.sg/main/v2/schoolquery",
as.character(exam_data$ID))
p <- ggplot(data=exam_data,
aes(x = MATHS)) +
geom_dotplot_interactive(aes(tooltip = tt,
onclick = exam_data$onclick),
stackgroups = TRUE,
binwidth = 1,
method = "histodot") +
scale_y_continuous(NULL,
breaks = NULL) +
labs(x ="Math Scores") +
theme(axis.line = element_blank(),
plot.background = element_rect(fill = "#F8F3E6", color = "#F8F3E6"))
girafe(
ggobj = p,
width_svg = 6,
height_svg = 6*0.618) Create interactive graphs using:
plot_ly()ggplotly()Adding color argument to code chunk to vary marker colors by specified category
moonrise_cols <- wes_palette("Moonrise2", type = "discrete")
p <- ggplot(data = exam_data,
aes(x = ENGLISH,
y = MATHS,
color = RACE,
text = paste("<b>English Score:</b>", ENGLISH, "<br><b>Math Score:</b>", MATHS,"<br>Race:", RACE))) +
geom_point(size = 1.5) +
labs(title = "Math and English Scores by Race",
x = "English Score",
y = "Math Score") +
scale_color_manual(values = wes_palette("Moonrise2", n = 4)) +
theme_grey() +
theme(plot.title = element_text(color = moonrise_cols[4], size = 14, face = "bold"),
axis.title.x = element_text(color = moonrise_cols[1], size = 10, face = "bold"),
axis.title.y = element_text(color = moonrise_cols[1], size = 10, face = "bold"),
plot.background = element_rect(fill = "#F8F3E6", color = "#F8F3E6")
)
ggplotly(p, tooltip = "text")This involves three steps:
highlight_key() of plotly package is used as shared datasubplot() of plotly package is used to place them side-by-sided <- highlight_key(exam_data)
p1 <- ggplot(data = d,
aes(x = MATHS,
y = ENGLISH,
text = paste("<b>Math Score:</b>", MATHS,"<br><b>English Score:", ENGLISH))) +
geom_point(size = 1, shape = 18) +
coord_cartesian(xlim = c(0,100),
ylim = c(0,100)) +
theme(plot.background = element_rect(fill = "#F8F3E6", color = "#F8F3E6"))
p2 <- ggplot(data = d,
aes(x = MATHS,
y = SCIENCE,
text = paste("<b>Math Score:</b>", MATHS,"<br><b>Science Score:", SCIENCE))) +
geom_point(size = 1) +
coord_cartesian(xlim = c(0,100),
ylim = c(0,100)) +
theme(plot.background = element_rect(fill = "#F8F3E6", color = "#F8F3E6"))
subplot(ggplotly(p1, tooltip = "text"),
ggplotly(p2, tooltip = "text"))Crosstalk is an add-on to the htmlwidgets package. It extends htmlwidgets with a set of classes, functions, and conventions for implementing cross-widget interactions (currently, linked brushing and filtering).
Limitations of Crosstalk:
DT package allow rendering of data objects as HTML tables
exam_data <- subset(exam_data, select = c(1:7))
d <- highlight_key(exam_data)
p <- ggplot(data = d,
aes(x = MATHS,
y = ENGLISH,
text = paste("<b>Math Score:</b>", MATHS,"<br><b>English Score:", ENGLISH))) +
geom_point(size = 1) +
coord_cartesian(xlim = c(0,100),
ylim = c(0,100)) +
theme(plot.background = element_rect(fill = "#F8F3E6", color = "#F8F3E6"))
gg <- highlight(ggplotly(p, tooltip = "text"),
"plotly_selected")
crosstalk::bscols(gg,
DT::datatable(d),
widths = 5) gganimate provides a range of new grammar classes that can be added to the plot object in order to customise how it should change with time.
transition_*() defines how the data should be spread out and how it relates to itself across timeview_*() defines how the positional scales should change along the animationshadow_*() defines how data from other points in time should be presented in the given point in timeenter_*()/exit_*() defines how new data should appear and how old data should disappear during the course of the animationease_aes() defines how different aesthetics should be eased during transitionsgifski converts video frames to GIF animations
*Importing Data**
This involves three steps:
transition_time() of gganimate is used to create transition through distinct states in time (i.e. Year)ease_aes() is used to control easing of aesthetics. The default is linear. Other methods are: quadratic, cubic, quartic, quintic, sine, circular, exponential, elastic, back, and bounceggplot(msia_pop, aes(x = Pct_Old, y = Pct_Young,
size = Population,
colour = Ethnicity)) +
geom_point(alpha = 0.7) +
scale_colour_manual(values = wes_palette("Darjeeling1")) +
scale_size(range = c(5, 25)) +
labs(title = 'Malaysian Population by Ethnicity for Year: {frame_time}',
subtitle = "Data Source: https://www.kaggle.com/datasets/jasonkwm/malaysia-demographic-20102019",
x = '% Aged',
y = '% Young') +
guides(size = "none") +
theme(legend.position = "bottom",
plot.background = element_rect(fill = "#F8F3E6", color = "#F8F3E6")) +
transition_time(Year) + #<<
ease_aes('linear') 
*Importing data**
ggplot(globalPop, aes(x = Old, y = Young,
size = Population,
colour = Country)) +
geom_point(alpha = 0.7,
show.legend = FALSE) +
scale_colour_manual(values = country_colors) +
scale_size(range = c(2, 12)) +
labs(title = 'Year: {frame_time}',
x = '% Aged',
y = '% Young') +
theme_gray() +
theme(plot.background = element_rect(fill = "#F8F3E6", color = "#F8F3E6")) +
transition_time(Year) +
ease_aes('linear') 
ggplotly() is used to convert the R graphic object into an animated svg object.
gg <- ggplot(globalPop,
aes(x = Old,
y = Young,
size = Population,
colour = Country)) +
geom_point(aes(size = Population,
frame = Year), #<<
alpha = 0.7,
show.legend = FALSE) +
scale_colour_manual(values = country_colors) +
scale_size(range = c(2, 12)) +
labs(x = '% Aged',
y = '% Young') +
theme_gray() +
theme(plot.background = element_rect(fill = "#F8F3E6", color = "#F8F3E6"))
ggplotly(gg)